#ifndef RP2CATALOG_H
#define RP2CATALOG_H

#include "Rp2System.h"

namespace Rp2
{

template <class T>
class Catalog
{
public:
    // The default catalog (for each class type Image, Texture, VertexProgram,
    // PixelProgram) is created in Main::Initialize and destroyed in
    // Main::Terminate (see Rp2Main.cpp).  The default catalog is stored in
    // ms_pkActive.
    //
    // Additional catalogs may be created by the application and are stored in
    // ms_apkCatalogs.  The catalogs are inserted into the array by the
    // constructor call and removed from the array by the destructor call.
    // Therefore, the default catalog is the first entry to be added to the
    // array (when created in Main::Initialize) and the last entry to be
    // removed from the array (when destroyed in Main::Terminate).

	Catalog(const std::string& rkName);
	~Catalog();

	const std::string& GetName() const;
	bool Insert(T* pkObject);
	bool Remove(T* pkObject);
	T* Find (const std::string& rkName);
	bool PrintContents(const std::string& rkFileName) const;

    // If the application changes the active catalog and wishes to restore the
    // previous catalog, it should do the following:
    //   Catalog<T>* pkPreviousCatalog = Catalog<T>::GetActive();
    //   Catalog<T>::SetActive(pkMyCatalog);
    //   <operations involving the active catalog)>
    //   Catalog<T>::SetActive(pkPreviousCatalog);
    static void SetActive (Catalog* pkActive);
    static Catalog* GetActive ();

    // Operations applied to the array of catalogs.  Objects of class T are
    // inserted into the active catalog during their construction.  Because
    // the active catalog at the time of destruction might be different, it
    // is necessary for the destructors to call RemoveAll.  The RemoveAll
    // function call iterates over the array of catalogs and attempts to
    // remove the object.  It is possible for an application to insert the
    // object into multiple catalogs, so RemoveAll must search all catalogs.
	static Catalog* GetCatalog(const std::string& rkName);
	static void SetActive(const std::string& rkName);
	static bool RemoveAll(T* ptObject);

private:
	std::string m_kName;

    typedef std::map<std::string,T*> Map;
    typedef typename Map::iterator MapIterator;
    typedef typename Map::const_iterator MapCIterator;
    Map m_kEntry;

    // The default catalog for each class type (Image, Texture,
    // VertexProgram, PixelProgram) is created in Main::Initialize and
    // destroyed in Main::Terminate (see Rp2Main.cpp).
    static Catalog* ms_pkActive;

    // Additional catalogs may be created by the application.  This array does
    // not contain the default catalog created by class Main.
	static std::vector<Catalog*> ms_apkCatalogs;
};

#include "Rp2Catalog.inl"

}

#endif